専用ドライバ無しでAuroraの高速フェイルオーバーに対応してみる
大栗です。
Auroraは通常のRDS for MySQLと比べると元々障害時の復旧が速いのですが、高速フェイルオーバーという2〜3秒でフェイルオーバーができる機能があります。ただし専用のドライバ(MariaDB Connector/Jなど)を利用することが一般的です。先日MySQL用のプロキシサーバであるProxySQLがv2にバージョンアップして、Auroraの高速フェイルオーバーに対応したのでご紹介します。
Releases · sysown/proxysql · GitHub v2.0.2
Auroraのフェイルオーバー
Auroraはシステム変数のinnodb_read_only
の値によって、Writer
かReader
のロールを判断できます。そのためinnodb_read_only
を定期的に確認してクエリをWriter
にルーティングすることで高速にフェイルオーバーができます。Auroraには書き込み専用のクラスターエンドポイントがありますが、切り替えまでも時間が少し遅く、切替時にReader
へアクセスしてしまうことがあるため注意が必要です。
Aurora MySQLの高速フェイルオーバーについては、以下のエントリーを御覧ください。こちらはJDBCドライバのMariaDB Connector/Jを利用しています。
ProxySQL
ProxySQLは高性能、高可用性なプロトコルを意識するMySQL及びフォーク(MariaDBやPercona Server)のプロキシです。ライセンスはGPLv3となっています。
ProxySQLはプロトコルを解釈するためコネクションプーリングなどができます。また管理インタフェースがSQLになっていて動的な設定が可能になっているもの特徴です。
以下のように設定ファイル(CONFIG FILE)からメモリに内容を明示的に呼び出して、ランタイム適用し、ディスク(SQLite)に書き込み永続化します。管理インタフェースはMySQL互換になっており、mysqlコマンドでログインできます。SQLを実行して内容を変更することもできます。ディスク(SQLite)に書き込んだものは、次回起動時に自動的に読み込まれます。一部のパラメータ(datadir
やerrorlog
)以外は設定ファイル(CONFIG FILE)から自動で読み込まれないため注意が必要です。
+-------------------------+ | RUNTIME | +-------------------------+ /|\ | | | [1] | [2] | | \|/ +-------------------------+ | MEMORY | +-------------------------+ _ /|\ | |\ | | \ [3] | [4] | \ [5] | \|/ \ +-------------------------+ +-------------------------+ | DISK | | CONFIG FILE | +-------------------------+ +-------------------------+
Source: Configuring ProxySQL
やってみた
事前準備として、Auroraクラスタを起動して、DBインスタンスを2台立ち上げておきます。DBのエンドポイントは以下のものとします。
- インスタンスエンドポイント
- aurora-1.a1b2c3d4e5f6.ap-northeast-1.rds.amazonaws.com
- aurora-2.a1b2c3d4e5f6.ap-northeast-1.rds.amazonaws.com
- クラスターエンドポイント
- cluster1.cluster-a1b2c3d4e5f6.ap-northeast-1.rds.amazonaws.com
またAuroraにアクセスするクライアントはAmazon Linux 2とします。使用するProxySQLはv2.0.2です。
手順としては
- ProxySQLのインストール
- ProxySQLの設定
- フェイルオーバーの確認
ProxySQLのインストール
ProxySQLのyumリポジトリを登録します。
$ cat <<EOF | sudo tee /etc/yum.repos.d/proxysql.repo > [proxysql_repo] > name= ProxySQL YUM repository > baseurl=http://repo.proxysql.com/ProxySQL/proxysql-2.0.x/centos/latest > gpgcheck=1 > gpgkey=http://repo.proxysql.com/ProxySQL/repo_pub_key > EOF
必要なパッケージをインストールします。
$ sudo yum install -y proxysql mariadb git
インストールされたProxySQLのファイルは以下となっています。
$ rpm -ql proxysql /etc/init.d/proxysql /etc/proxysql.cnf /usr/bin/proxysql /usr/share/proxysql/tools/proxysql_galera_checker.sh /usr/share/proxysql/tools/proxysql_galera_writer.pl
現バージョンのrpmにはsystemd用のユニットファイルが入っていないようなので、リポジトリから持ってきます。
$ cd $ git clone https://github.com/sysown/proxysql.git $ sudo cp ./proxysql/systemd/system/proxysql.service /etc/systemd/system/ $ sudo systemctl daemon-reload
systemdに登録します。
$ sudo systemctl enable proxysql.service Created symlink from /etc/systemd/system/multi-user.target.wants/proxysql.service to /etc/systemd/system/proxysql.service.
ProxySQLの設定
ProxySQLの設定ファイルを記述します。admin_variables
では管理インタフェースのパラメータを定義します。mysql_variables
ではMySQLのパラメータを定義します。
datadir="/var/lib/proxysql" errorlog="/var/log/proxysql/proxysql.log" admin_variables= { admin_credentials="admin:admin" mysql_ifaces="127.0.0.1:6032;/tmp/proxysql_admin.sock" } mysql_variables= { threads=4 max_connections=2048 default_query_delay=0 default_query_timeout=36000000 have_compress=true hostgroup_manager_verbose=0 poll_timeout=2000 interfaces="127.0.0.1:6033;/tmp/proxysql.sock" default_schema="information_schema" stacksize=1048576 server_version="5.7.12B" connect_timeout_server=3000 max_allowed_packet=67108864 monitor_username="awsuser" monitor_password="mypassword" monitor_history=600000 monitor_connect_interval=60000 monitor_ping_interval=1000 monitor_read_only_interval=500 monitor_read_only_timeout=500 ping_interval_server_msec=120000 ping_timeout_server=500 commands_stats=true sessions_sort=true connect_retries_on_failure=10 }
ログファイルのパスerrorlog
を/var/log/proxysql/proxysql.log
にしたのでディレクトリを作成します。(デフォルトは/var/lib/proxysql/proxysql.log
です。)
$ sudo mkdir /var/log/proxysql $ sudo chown proxysql:proxysql /var/log/proxysql
ここでProxySQLを起動します。
$ sudo systemctl start proxysql
ProxySQLの管理インタフェースにログインします。
$ mysql -uadmin -padmin -h 127.0.0.1 -P 6032 Welcome to the MariaDB monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.7.12B (ProxySQL Admin Module) Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MySQL [(none)]>
コンフィグファイルのmysql_users
の内容(バックエンドのAuroraのユーザー情報)をロードして、ランタイムに適用し、ディスクに永続化します。ランタイムに適用した後にランタイムからメモリに内容を保存しているのはパスワードをハッシュ化するためです。
MySQL [(none)]> INSERT INTO mysql_users (username,password,active,default_hostgroup,default_schema,transaction_persistent) values ('awsuser','mypassword',1,1,'mydb',1); Query OK, 1 row affected (0.00 sec) MySQL [(none)]> LOAD MYSQL USERS TO RUNTIME; SAVE MYSQL USERS FROM RUNTIME; SAVE MYSQL USERS TO DISK; Query OK, 1 row affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.01 sec)
Auroraの各DBインスタンスのエンドポイントを登録します。少し分かりにくいのですが、現在のWriter
のエンドポイントをhostgroup_idが1と2に登録して、それ以外のインスタンスのエンドポイントをhostgroup_idが2に登録して下さい。mysql_replication_hostgroups
でcheck_type
をinnodb_read_only
に設定することでAuroraの高速フェイルオーバーに対応できます。
MySQL [(none)]> INSERT INTO mysql_servers (hostname,hostgroup_id,port,weight,max_connections) VALUES ('aurora-1.a1b2c3d4e5f6.ap-northeast-1.rds.amazonaws.com',1,3306,1000,2000); Query OK, 1 row affected (0.00 sec) MySQL [(none)]> INSERT INTO mysql_servers (hostname,hostgroup_id,port,weight,max_connections) VALUES ('aurora-1.a1b2c3d4e5f6.ap-northeast-1.rds.amazonaws.com',2,3306,1000,2000); Query OK, 1 row affected (0.00 sec) MySQL [(none)]> INSERT INTO mysql_servers (hostname,hostgroup_id,port,weight,max_connections) VALUES ('aurora-2.a1b2c3d4e5f6.ap-northeast-1.rds.amazonaws.com',2,3306,1000,2000); Query OK, 1 row affected (0.00 sec) MySQL [(none)]> INSERT INTO mysql_replication_hostgroups(writer_hostgroup,reader_hostgroup,comment,check_type) VALUES (1,2,'aws-aurora','innodb_read_only'); Query OK, 1 row affected (0.00 sec) MySQL [(none)]> LOAD MYSQL SERVERS TO RUNTIME; SAVE MYSQL SERVERS TO DISK; Query OK, 0 rows affected (0.01 sec) Query OK, 0 rows affected (0.01 sec)
コンフィグファイルのmysql_variables
の内容をロードして、ランタイムに適用し、ディスクに永続化します。
MySQL [(none)]> LOAD MYSQL VARIABLES FROM CONFIG; LOAD MYSQL VARIABLES TO RUNTIME; SAVE MYSQL VARIABLES TO DISK; Query OK, 25 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 110 rows affected (0.00 sec)
コンフィグファイルのadmin_variables
の内容をロードして、ランタイムに適用し、ディスクに永続化します。
MySQL [(none)]> LOAD ADMIN VARIABLES FROM CONFIG; LOAD ADMIN VARIABLES TO RUNTIME; SAVE ADMIN VARIABLES TO DISK; Query OK, 2 rows affected (0.01 sec) Query OK, 0 rows affected (0.00 sec) Query OK, 32 rows affected (0.00 sec)
これでProxySQLのフェイルオーバーの設定は完了です。
フェイルオーバーの確認
ここからフェイルオーバーの挙動を確認します。
確認のために以下のようなスクリプトを作成しました。
#! /bin/bash while true do DATETIME=$(date "+%Y-%m-%d %T.%N") (echo "select '${DATETIME}', now(3), @@hostname, @@innodb_read_only;" | mysql -uawsuser -pmypassword -h 127.0.0.1 -P 6033 -s) & sleep 0.5 done
Auroraをフェイルオーバーさせてからtest1.sh
を実行してみます。するとアクセスエラーが出ずに新しい接続ができるまでProxySQLが待ってアクセスさせます。
$ test1.sh 2019-03-03 22:57:42.892678638 2019-03-03 22:57:42.898 ip-10-7-1-188 0 2019-03-03 22:57:43.394422969 2019-03-03 22:57:43.400 ip-10-7-1-188 0 2019-03-03 22:57:43.896195975 2019-03-03 22:57:43.901 ip-10-7-1-188 0 2019-03-03 22:57:45.903019170 2019-03-03 22:57:46.682 ip-10-7-2-55 0 2019-03-03 22:57:44.397923446 2019-03-03 22:57:46.682 ip-10-7-2-55 0 2019-03-03 22:57:45.401376866 2019-03-03 22:57:46.712 ip-10-7-2-55 0 2019-03-03 22:57:44.899675289 2019-03-03 22:57:46.715 ip-10-7-2-55 0 2019-03-03 22:57:46.404922113 2019-03-03 22:57:46.716 ip-10-7-2-55 0 2019-03-03 22:57:46.906811093 2019-03-03 22:57:46.912 ip-10-7-2-55 0 2019-03-03 22:57:47.408530454 2019-03-03 22:57:47.414 ip-10-7-2-55 0
タイミングが悪いと接続エラーが1回発生して、他は接続に時間がかかっていますが正常にアクセスできています。
$ test1.sh 2019-03-03 16:50:40.986009984 2019-03-03 16:50:40.992 ip-10-7-1-188 0 2019-03-03 16:50:41.487770905 2019-03-03 16:50:41.493 ip-10-7-1-188 0 2019-03-03 16:50:41.989562015 2019-03-03 16:50:41.995 ip-10-7-1-188 0 2019-03-03 16:50:42.491364838 2019-03-03 16:50:42.497 ip-10-7-1-188 0 2019-03-03 16:50:42.993140431 2019-03-03 16:50:42.999 ip-10-7-1-188 0 2019-03-03 16:50:43.494924476 2019-03-03 16:50:43.500 ip-10-7-1-188 0 2019-03-03 16:50:43.996640031 2019-03-03 16:50:44.002 ip-10-7-1-188 0 ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query 2019-03-03 16:50:46.505309320 2019-03-03 16:50:47.200 ip-10-7-2-55 0 2019-03-03 16:50:47.007015427 2019-03-03 16:50:47.201 ip-10-7-2-55 0 2019-03-03 16:50:46.003570112 2019-03-03 16:50:47.225 ip-10-7-2-55 0 2019-03-03 16:50:45.000181268 2019-03-03 16:50:47.227 ip-10-7-2-55 0 2019-03-03 16:50:45.501884631 2019-03-03 16:50:47.229 ip-10-7-2-55 0 2019-03-03 16:50:47.508841424 2019-03-03 16:50:47.514 ip-10-7-2-55 0 2019-03-03 16:50:48.010660980 2019-03-03 16:50:48.017 ip-10-7-2-55 0 2019-03-03 16:50:48.512389025 2019-03-03 16:50:48.517 ip-10-7-2-55 0 2019-03-03 16:50:49.014104387 2019-03-03 16:50:49.020 ip-10-7-2-55 0 2019-03-03 16:50:49.515826670 2019-03-03 16:50:49.521 ip-10-7-2-55 0
同様の確認をクラスターエンドポイントに対して実行して挙動の違いを確認します。
#! /bin/bash while true do DATETIME=$(date "+%Y-%m-%d %T.%N") (echo "select '${DATETIME}', now(3), @@hostname, @@innodb_read_only;" | mysql -uawsuser -pmypassword -h cluster1.cluster-a1b2c3d4e5f6.ap-northeast-1.rds.amazonaws.com -s) & sleep 0.5 done
クラスターエンドポイントのフェイルオーバーの場合は、5秒程度アクセスができずエラーになります。その後に接続が可能なりますが、Writer
にアクセスせず'Reader'にアクセスしている接続があります。接続断から正常にアクセスができるようになるまで10秒以上かかり、切り替え直後はReader
へ接続することがあります。コネクションプールをしている場合はWriter
と認識しながらReader
へ接続してしまう恐れがあります。
$ test2.sh 2019-03-03 17:07:38.481261780 2019-03-03 17:07:38.527 ip-10-7-2-55 0 2019-03-03 17:07:38.982959640 2019-03-03 17:07:38.994 ip-10-7-2-55 0 2019-03-03 17:07:39.484645225 2019-03-03 17:07:39.498 ip-10-7-2-55 0 2019-03-03 17:07:39.986400140 2019-03-03 17:07:40.036 ip-10-7-2-55 0 2019-03-03 17:07:40.488067076 2019-03-03 17:07:40.518 ip-10-7-2-55 0 2019-03-03 17:07:40.989787855 2019-03-03 17:07:41.008 ip-10-7-2-55 0 2019-03-03 17:07:41.491802337 2019-03-03 17:07:41.508 ip-10-7-2-55 0 2019-03-03 17:07:41.993609782 2019-03-03 17:07:42.049 ip-10-7-2-55 0 2019-03-03 17:07:42.495282630 2019-03-03 17:07:42.508 ip-10-7-2-55 0 2019-03-03 17:07:42.997026431 2019-03-03 17:07:43.078 ip-10-7-2-55 0 2019-03-03 17:07:43.498786054 2019-03-03 17:07:43.522 ip-10-7-2-55 0 ERROR 2003 (HY000): Can't connect to MySQL server on 'cluster1.cluster-cahdiejcylf2.ap-northeast-1.rds.amazonaws.com' (111) ERROR 2003 (HY000): Can't connect to MySQL server on 'cluster1.cluster-cahdiejcylf2.ap-northeast-1.rds.amazonaws.com' (111) ERROR 2003 (HY000): Can't connect to MySQL server on 'cluster1.cluster-cahdiejcylf2.ap-northeast-1.rds.amazonaws.com' (111) ERROR 2003 (HY000): Can't connect to MySQL server on 'cluster1.cluster-cahdiejcylf2.ap-northeast-1.rds.amazonaws.com' (111) ERROR 2003 (HY000): Can't connect to MySQL server on 'cluster1.cluster-cahdiejcylf2.ap-northeast-1.rds.amazonaws.com' (111) ERROR 2003 (HY000): Can't connect to MySQL server on 'cluster1.cluster-cahdiejcylf2.ap-northeast-1.rds.amazonaws.com' (111) ERROR 2003 (HY000): Can't connect to MySQL server on 'cluster1.cluster-cahdiejcylf2.ap-northeast-1.rds.amazonaws.com' (111) ERROR 2003 (HY000): Can't connect to MySQL server on 'cluster1.cluster-cahdiejcylf2.ap-northeast-1.rds.amazonaws.com' (111) 2019-03-03 17:07:48.014351001 2019-03-03 17:07:48.154 ip-10-7-2-55 1 2019-03-03 17:07:48.516025754 2019-03-03 17:07:48.637 ip-10-7-1-188 0 2019-03-03 17:07:49.017779788 2019-03-03 17:07:49.143 ip-10-7-1-188 0 2019-03-03 17:07:49.519452710 2019-03-03 17:07:49.572 ip-10-7-2-55 1 2019-03-03 17:07:50.021254718 2019-03-03 17:07:50.081 ip-10-7-1-188 0 2019-03-03 17:07:50.522961847 2019-03-03 17:07:50.579 ip-10-7-1-188 0 2019-03-03 17:07:51.024747160 2019-03-03 17:07:51.046 ip-10-7-2-55 1 2019-03-03 17:07:51.526463867 2019-03-03 17:07:51.592 ip-10-7-1-188 0 2019-03-03 17:07:52.028177070 2019-03-03 17:07:52.050 ip-10-7-2-55 1 2019-03-03 17:07:52.529906556 2019-03-03 17:07:52.550 ip-10-7-1-188 0 2019-03-03 17:07:53.031710290 2019-03-03 17:07:53.053 ip-10-7-1-188 0 2019-03-03 17:07:53.533451786 2019-03-03 17:07:53.595 ip-10-7-2-55 1 2019-03-03 17:07:54.035212374 2019-03-03 17:07:54.090 ip-10-7-1-188 0 2019-03-03 17:07:54.537028924 2019-03-03 17:07:54.551 ip-10-7-2-55 1 2019-03-03 17:07:55.038785867 2019-03-03 17:07:55.053 ip-10-7-1-188 0 2019-03-03 17:07:55.540528655 2019-03-03 17:07:55.624 ip-10-7-1-188 0 2019-03-03 17:07:56.042264895 2019-03-03 17:07:56.102 ip-10-7-1-188 0 2019-03-03 17:07:56.543907075 2019-03-03 17:07:56.603 ip-10-7-1-188 0 2019-03-03 17:07:57.045989555 2019-03-03 17:07:57.060 ip-10-7-1-188 0 2019-03-03 17:07:57.547804169 2019-03-03 17:07:57.598 ip-10-7-1-188 0 2019-03-03 17:07:58.049725021 2019-03-03 17:07:58.066 ip-10-7-1-188 0 2019-03-03 17:07:58.551453339 2019-03-03 17:07:58.567 ip-10-7-1-188 0 2019-03-03 17:07:59.053244992 2019-03-03 17:07:59.104 ip-10-7-1-188 0 2019-03-03 17:07:59.554931207 2019-03-03 17:07:59.571 ip-10-7-1-188 0
さいごに
今まで高速フェイルオーバーを行うにはMariaDB Connector/Jの様なドライバを使うか、HAProxy 1.6以上で外部スクリプトのチェック(fujiwaraさんが実施しています)を行うなどの方法がありました。MariaDB Connector/Jの場合はJVMに限定されるし、HAProxyの場合はAmazon Linuxのリポジトリのバージョンが1.5のため使用できずHAProxy 1.6以降の信用できるリポジトリのrpmが出回っていない状態でした(自分で野良ビルドしたくない派)。
ProxySQLがv2になり公式のrpmで動かせるようになったので簡単に試せるようになりました。Auroraを利用する場合にはProxySQLをセットで使用する事を検討しても良いかもしれません。注意点として、別途ProxySQLを別インスタンスに立てるとその障害が発生した場合の事を考えなければならないので、個人的にはAPサーバに同居させることをお勧めします。